/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uk.ac.bath.base;

import java.util.Comparator;
import uk.ac.bath.util.MyRandom;

/**
 *
 *
 * @author pjl
 */
public class Gene extends AbstractGene {

    public boolean bits[];
  
    private int nBits;


    public Gene(int nBits, boolean randomize) {
        bits = new boolean[nBits];
        this.nBits = nBits;
     
        if (randomize) {
            randomize();
        }
    }

    public void randomize() {
        for (int i = 0; i < nBits; i++) {
            if (MyRandom.nextInt(2) == 1) {
                bits[i] = true;
            } else {
                bits[i] = false;
            }
        }
    }

    public int compareTo(Object oo) {

        Gene o = (Gene) oo;
        if (fitness > o.fitness) {
            return 1;
        } else if (fitness < o.fitness) {
            return -1;
        }

        if (id > o.id) {
            return 1;
        } else if (id < o.id) {
            return -1;
        }

        return 0; // same Gene !!!!

    }

    /**
     * (pinched from pole-sane.c)
     *
     * decode_weight will decode a floating point weight from an size-bit
     * string.  The bits are decoded as follows:
     * 0 - sign
     * 1-expSize - exponent
     * (expSize+1)-(size-1) - mantissa
     *  The exponent is encoded as a sign-magnitude number.  The mantissa
     *  has a hidden 1 to the left of the decimal point.
     *
     * @param start
     * @param size
     * @param expSize
     * @return
     */
    public float floatAt(int start, int size, int expSize) {

        int i, j;
        int stop;

        float mantissa = 0.0f, exponent = 0.0f, weight;

        stop = size + start;

        i = start + 1;
        for (j = 1; j < expSize; ++j) {
            exponent = (exponent * 2);

           if (bits[i + j]) {
                exponent += 1.0f;
            }
        }

        if (bits[i]) {
            exponent = -exponent;
        }

       //  System.out.println("exp=" + exponent);

        j = start + expSize;
        for (i = stop - 1; i > j; --i) {
            mantissa = mantissa / 2.0f;
            if (bits[i]) {
                mantissa += 1;
            }
        }

        mantissa = mantissa / 2.0f + 1.0f;  /*add hidden bit*/

     //   System.out.println("mant=" + mantissa);

        weight = (float) (mantissa*Math.pow(2,exponent));

//        for (i = 0; i < exponent; ++i) {
//            weight = weight * mantissa;
//        }
        if (bits[start]) {
            weight = -weight;
        }
        return weight;
    }

    /** decode_bits will decode a binary number contained in a character
    string pointed to by bit.  decode_bits starts at index start and
    continues for size bits.
     **/
    public int unsignedAt(int start, int size) {
        int i;
        int stop, total = 0;
        stop = size + start;
        for (i = start; i < stop; ++i) {
            total = (total * 2);
            if (bits[i]) {
                total += 1;
            }
        }
        return total;
    }

    public String toString() {
        String x = "";

        for (int i = 0; i < nBits; i++) {
            if (bits[i]) {
                x += '1';
            } else {
                x += '0';
            }

        }
        return x;

    }

  
    
    public static void main(String args[]) {

        for (int i = 0; i < 256; i++) {
            Gene g = new Gene(16, true);
            System.out.println(g + " > " + g.floatAt(0, 16, 3));
        }
    }
}
